package com.jenkins.test.proxy.scan;

import com.jenkins.test.proxy.example.BaseDaoProxyFactory;
import com.jenkins.test.proxy.example.DaoMark;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Set;

/**
 * @version V0.0.1
 * @ClassName: {@link DaoScanClassPathBeanDefinitionScanner}
 * @Description: DaoScanClassPathBeanDefinitionScanner
 * @author: Lanzhou
 * @date: 2022/1/23 15:59
 * @Copyright:2019 All rights reserved.
 * 注意：本内容仅限于本人开发与维护，禁止外泄以及用于其他的商业目
 */
public class DaoScanClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {

    public DaoScanClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    /**
     * 扫描过滤器, 定义扫描的过滤规则
     */
    @Override
    protected void registerDefaultFilters() {
        // 扫描规则 - 只扫描我们带有 @DaoMark 注解的接口
        this.addIncludeFilter(new AnnotationTypeFilter(DaoMark.class));
    }

    /**
     * 判断注解Bean的定义信息是否是接口和有被依赖使用(未被注入则不初始化当前Bean, 只能, 棒!!!)
     *
     * @param beanDefinition 注解信息
     * @return 是否满足候选组件
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
        processBeanDefinitions(beanDefinitionHolders);
        //返回的是 BeanDefinition
        return beanDefinitionHolders;
    }

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitionHolders) {
        beanDefinitionHolders.forEach(e -> {
            GenericBeanDefinition definition = (GenericBeanDefinition) e.getBeanDefinition();
            //这里是相当于调用BaseDaoProxyFactory中的setInterfaceClass()方法，详细的可以了解spring相关资料
            definition.getPropertyValues().add("interfaceClass", definition.getBeanClassName());
            // FactoryBean是一种特殊的Bean，这里的BeanClass是生成Bean实例的工厂，不是Bean本身。其返回的是该工厂Bean的getObject方法所返回的对象。
            definition.setBeanClass(BaseDaoProxyFactory.class);
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        });
    }

}
